package com.thprojects.myphotomemories.view;

import java.util.LinkedList;
import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

import com.thprojects.imagefilters.Brightness;
import com.thprojects.imagefilters.Emboss;
import com.thprojects.imagefilters.Filter;
import com.thprojects.imagefilters.Gamma;
import com.thprojects.imagefilters.GaussianBlur;
import com.thprojects.imagefilters.Greyscale;
import com.thprojects.imagefilters.Reflection;
import com.thprojects.imagefilters.SepiaToning;
import com.thprojects.imagefilters.Sharpen;
import com.thprojects.myphotomemories.R;
import com.thprojects.myphotomemories.controller.FSController;
import com.thprojects.myphotomemories.controller.GuiController;
import com.thprojects.myphotomemories.model.Photo;

import exception.PhotoSourceNotFoundException;
import exception.SDNotReadyException;



public class EffectsPhotoView extends Activity{
	FSController mFSController;
	Button mSave, mCancel;
	Photo mPhoto;
	Bitmap[] mBmp = new Bitmap[9];
	ImageView[] mImgV = new ImageView[9]; 
	Filter[] mFilters = new Filter[9];
	Bitmap mCur;
	Bitmap mCurSmall;
	ProgressDialog mPDialog;
	int mPrevW = 100;
	List<Filter> mAppliedFilters = new LinkedList<Filter>();
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.photo_effects);
		
		Intent intent = getIntent();
        mPhoto = (Photo) intent.getParcelableExtra("photo");
        
        mFSController = FSController.getFSController(this);
        
        mSave = (Button)findViewById(R.id.save_photo_effect);
        mSave.setOnClickListener(new OnClickListener() {	
			public void onClick(View v) {
				SavePhotoTask at = new SavePhotoTask();
		        at.execute();
			}
		});
        mCancel = (Button)findViewById(R.id.cancel_photo_effect);
        mCancel.setOnClickListener(new OnClickListener() {	
			public void onClick(View v) {
				GuiController.showPhoto(EffectsPhotoView.this, mPhoto);
				finish();
			}
		});
        
        
        mFilters[0] = new Reflection();
        mFilters[1] = new SepiaToning();
        mFilters[2] = new Emboss();
        mFilters[3] = new Sharpen();
        //tiene di volta in volta il filtro selezionato
        mFilters[4] = null;
        mFilters[5] = new GaussianBlur();
        mFilters[6] = new Greyscale();
        mFilters[7] = new Gamma();
        mFilters[8] = new Brightness();
        
        mImgV[0] = (ImageView)findViewById(R.id.eff_reflection);
        mImgV[1] = (ImageView)findViewById(R.id.eff_sepia);
        mImgV[2] = (ImageView)findViewById(R.id.eff_emboss);
        mImgV[3] = (ImageView)findViewById(R.id.eff_contrast);
        mImgV[4] = (ImageView)findViewById(R.id.eff_result);
        mImgV[5] = (ImageView)findViewById(R.id.eff_blur);
        mImgV[6] = (ImageView)findViewById(R.id.eff_greyscale);
        mImgV[7] = (ImageView)findViewById(R.id.eff_gamma);
        mImgV[8] = (ImageView)findViewById(R.id.eff_brightness); 
        
        
        InitTask at = new InitTask();
        at.execute();

	}
	
	private void setResultImage(Bitmap img){
		mImgV[4].setImageBitmap(img);
	}
	

	
	private void updateResultImage(Bitmap newCurSmall){		
		//preview
		mCurSmall = newCurSmall.copy(Bitmap.Config.ARGB_8888, false);
		
		applyPreviewFilters();
		applyResultFilter();
		
	}
	
	private void applyResultFilter(){
    	mBmp[4] = mFilters[4].apply(mCur);
    	//mCur contiene ora il vecchio mBmp[4]
    	if (mCur != null) mCur.recycle();
    	//assegno a mCur il nuovo mBmp[4]
    	mCur = mBmp[4];
    	mAppliedFilters.add(mFilters[4]);
	}
	
	private void applyPreviewFilters(){
		for (int i=0; i<9; i++){
			if(i==4) continue;
        	if (mBmp[i] != null) mBmp[i].recycle();
        	mBmp[i] = mFilters[i].apply(mCurSmall);
        }
	}
	
	private class InitTask extends AsyncTask<Void, Void, Void>{

		@Override
		protected Void doInBackground(Void... params) {
			applyPreviewFilters();
			return null;
		}
	
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);

			setResultImage(mCur);
			
			for (int i=0; i<9; i++){
	        	if (i==4) continue;
	        	final int c = i;
	        	mImgV[i].setImageBitmap(mBmp[i]);
	        	mImgV[i].setOnClickListener(new OnClickListener() {			
					public void onClick(View v) {
						mFilters[4] = mFilters[c];
						UpdateTask at = new UpdateTask();
				        at.execute(mBmp[c]);
					}
				});
	        }
			mPDialog.dismiss();
		}
	
		@Override
		protected void onPreExecute() {
			mPDialog = ProgressDialog.show(EffectsPhotoView.this, "", "Loading effects. Please wait...", true);
			//TODO dimensioni bitmap
	        try {
				mCur = mFSController.decodeSampledBitmap(mPhoto.getPath(), 2*mPrevW, 2*mPrevW);
				mCurSmall = mFSController.decodeSampledBitmap(mPhoto.getPath(), mPrevW, mPrevW);
			} catch (PhotoSourceNotFoundException e) {
				GuiController.showError(EffectsPhotoView.this, e.getMessage());
			} catch (SDNotReadyException e) {
				GuiController.showError(EffectsPhotoView.this, e.getMessage());
			}
	        
		}
    	
    }
	
	private class UpdateTask extends AsyncTask<Bitmap, Void, Void>{

		@Override
		protected Void doInBackground(Bitmap... params) {
			updateResultImage(params[0]);
			return null;
		}
	
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			for (int i=0; i<9; i++){
				mImgV[i].setImageBitmap(mBmp[i]);
	        }
			mPDialog.dismiss();
		}
	
		@Override
		protected void onPreExecute() {
			mPDialog = ProgressDialog.show(EffectsPhotoView.this, "", "Applying effect. Please wait...", true);
			//empty imageViews		
			for (int i=0; i<9; i++){
				mImgV[i].setImageBitmap(null);
	        }
		}
    	
    }
	
	private class SavePhotoTask extends AsyncTask<Void, Void, Void>{

		@Override
		protected Void doInBackground(Void... params) {
			Bitmap bmp = BitmapFactory.decodeFile(mPhoto.getPath());
			Bitmap old;
			for (Filter f: mAppliedFilters){
				old = bmp;
				bmp = f.apply(bmp);
				old.recycle();
			}
			try {
				mFSController.savePicture(bmp, mPhoto.getPath());
				GuiController.showPhoto(EffectsPhotoView.this, mPhoto);
				finish();
			} catch (SDNotReadyException e) {
				GuiController.showError(EffectsPhotoView.this, e.getMessage());
			}
			bmp.recycle();
			
			return null;
		}
	
		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			mPDialog.dismiss();
		}
	
		@Override
		protected void onPreExecute() {
			mPDialog = ProgressDialog.show(EffectsPhotoView.this, "", "Saving image. Please wait...", true);
		}
    	
    }
	
}
